﻿using System;
using System.Collections.Generic;
using BlobNet.Base.Collections;
using BlobNet.Base.Storage;
using BlobNet.TestsCommon.UnitTests.Dummy;
using BlobNet.TestsCommon.Utils;
using NUnit.Framework;
using Rhino.Mocks;
using Rhino.Mocks.Impl;

namespace BlobNet.Base.Tests.UnitTests.StorageTests
{
    

    //TODO: finish tests until coverage is 100%
    //TODO:refactor tests
    [TestFixture]
    [Category("Unit Tests")]
    public class MemoryStorageTests
    {
        [TestFixtureSetUp]
        public void StartFixture()
        {
            RhinoMocks.Logger = new TextWriterExpectationLogger(Console.Out);
        }

        [Test]
        public void Can_Retrieve_BlobPart_PropertyValue()
        {
            Guid idEntity = Guid.NewGuid();
            BlobDomain blobDomain = TestsHelper.GetDummyBlobDomain();
            var expected = new DummyBlobPart(blobDomain);
            var target = new MemoryStorage(idEntity, blobDomain);

            target.Cache["TestProperty"] = expected;

            var actual = target.GetStatusValue<DummyBlobPart>("TestProperty");
            Assert.AreSame(expected, actual);
        }

        [Test]
        public void Can_Retrieve_IEnumerable_PropertyValue()
        {
            Guid idEntity = Guid.NewGuid();
            var target = new MemoryStorage(idEntity, TestsHelper.GetDummyBlobDomain());
            IEnumerable<int> expected = new List<int> {666};

            target.Cache["ListProperty"] = expected;

            var actual = target.GetStatusValue<IEnumerable<int>>("ListProperty");
            Assert.AreSame(expected, actual);
        }

        [Test]
        public void Can_Retrieve_NonInitialized_PropertyValue()
        {
            Guid idEntity = Guid.NewGuid();
            var target = new MemoryStorage(idEntity, TestsHelper.GetDummyBlobDomain());

            Assert.DoesNotThrow(() => target.GetStatusValue<int>("propertyName"));
            Assert.IsTrue(target.GetStatusValue<int>("propertyName") == 0);
            Assert.IsNull(target.GetStatusValue<DummyObject>("propertyName"));
        }

        [Test]
        public void Can_Retrieve_Object_PropertyValue()
        {
            Guid idEntity = Guid.NewGuid();
            var target = new MemoryStorage(idEntity, TestsHelper.GetDummyBlobDomain());
            var expected = new object();

            target.Cache["TestProperty"] = expected;

            var actual = target.GetStatusValue<object>("TestProperty");
            Assert.AreSame(expected, actual);
        }

        [Test]
        public void Can_Retrieve_PropertyValue()
        {
            //arrange

            Guid idEntity = Guid.NewGuid();
            var target = new MemoryStorage(idEntity, TestsHelper.GetDummyBlobDomain());

            string expected = "String sample";
            string testProperty = "SampleProperty";

            //Act
            target.Cache.Add(testProperty, expected);
            var actual = target.GetStatusValue<string>(testProperty);

            //Assert
            Assert.IsTrue(actual == expected);
        }

        [Test]
        [Ignore]
        public void Can_GetItems()
        {
            throw new NotImplementedException();
        }

        [Test]
        public void Can_Save_BlobPart_PropertyValue()
        {
            Guid idEntity = Guid.NewGuid();
            BlobDomain blobDomain = TestsHelper.GetDummyBlobDomain();
            var target = new MemoryStorage(idEntity, blobDomain);
            var expected = new DummyBlobPart(blobDomain);

            Assert.DoesNotThrow(() => target.SetStatusValue("TestProperty", expected));

            object actual = target.Cache["TestProperty"];
            Assert.AreSame(expected, actual);
        }




        [Test]
        public void Can_Save_PropertyValue()
        {
            //arrange
            Guid idEntity = Guid.NewGuid();
            var target = new MemoryStorage(idEntity, TestsHelper.GetDummyBlobDomain());
            string expected = "String sample";
            string testProperty = "SampleProperty";

            //Act
            target.SetStatusValue(testProperty, expected);
            var actual = (string) target.Cache[testProperty];

            //Assert
            Assert.IsTrue(actual == expected);
        }

        [Test]
        public void Can_Save_BlobListOfBlobPart_PropertyValue()
        {
            Guid idEntity = Guid.NewGuid();
            BlobDomain blobDomain = TestsHelper.GetDummyBlobDomain();
            var target = new MemoryStorage(idEntity, blobDomain);
            var expected = new BlobList<DummyBlobPart>(blobDomain) {new DummyBlobPart(blobDomain)};

            Assert.DoesNotThrow(() => target.SetStatusValue("ListProperty", expected));

            var actual = (IList<DummyBlobPart>) target.Cache["ListProperty"];
            Assert.AreEqual(expected[0], actual[0]);
        }

        [Test]
        public void Cant_Save_IListOfBlobPart_PropertyValue()
        {
            Guid idEntity = Guid.NewGuid();
            BlobDomain blobDomain = TestsHelper.GetDummyBlobDomain();
            var target = new MemoryStorage(idEntity, blobDomain);
            IList<DummyBlobPart> expected = new List<DummyBlobPart>
                                                      {new DummyBlobPart(blobDomain)};

            Assert.Throws(typeof (NotSupportedException), () => target.SetStatusValue("ListProperty", expected));
        }

        [Test]
        public void Cant_Save_IListOf_NonSupportedType_PropertyValue()
        {
            Guid idEntity = Guid.NewGuid();
            var target = new MemoryStorage(idEntity, TestsHelper.GetDummyBlobDomain());
            IList<DummyObject> expected = new List<DummyObject> {new DummyObject("aa")};

            Assert.Throws(typeof (NotSupportedException), () => target.SetStatusValue("ListProperty", expected));
        }

        [Test]
        public void Cant_Save_NonSupported_Object_PropertyValue()
        {
            Guid idEntity = Guid.NewGuid();
            var target = new MemoryStorage(idEntity, TestsHelper.GetDummyBlobDomain());
            var expected = new object();

            Assert.Throws(typeof (NotSupportedException), () => target.SetStatusValue("TestProperty", expected));
        }

        //TODO: check format migration

        [Test]
        public void Can_Store_Item()
        {
            throw new NotImplementedException();
        }

        [Test]
        public void Can_Update_Relation_When_1_1()
        {
            throw new NotImplementedException();
        }

        [Test]
        public void Can_Update_Relation_When_n_1()
        {
            throw new NotImplementedException();
        }

        [Test]
        public void Can_Update_Relation_When_1_n()
        {
            throw new NotImplementedException();
        }

        [Test]
        public void Can_Update_Relation_When_n_m()
        {
            throw new NotImplementedException();
        }
    }
}